/**
 * 一、js执行顺序，原型链，继承，构造函数，深拷贝，字符串去重，跨域，设计模式，排序算法，作用域，箭头函数，绑定this有几种方式，用setTimeOut模拟setInterval，session与cookie的区别，浏览器缓存
 * 答：原型链？
 *    答：在JavaScript中，每当定义一个函数数据类型(普通函数、类)时候，都会天生自带一个prototype属性，这个属性指向函数的原型对象，并且这个属性是一个对象数据类型的值。
 *    每一个对象数据类型(普通的对象、实例、prototype......)也天生自带一个属性__proto__，属性值是当前实例所属类的原型(prototype)。原型对象中有一个属性constructor, 它指向函数对象。
 * 
 *    深拷贝？
 *    答：浅拷贝：Object.assign()、var cloneObj = { ...obj };、Array.prototype.slice()
 *       深拷贝：JSON.stringify()、函数库lodash，也有提供_.cloneDeep用来做深拷贝、$.extend(true, {}, obj1)
 *              function deepClone(obj) {
                    var cloneObj = {}; //在堆内存中新建一个对象
                    for(var key in obj){ //遍历参数的键
                        if(typeof obj[key] ==='object'){ 
                            cloneObj[key] = deepClone(obj[key]) //值是对象就再次调用函数
                        }else{
                            cloneObj[key] = obj[key] //基本类型直接复制值
                        }
                    }
                    return cloneObj 
                }
 * 
 *    字符串去重？
 *    答：ES6去重、正则去重、search去重、普通for去重、indexOf / includes去重、对象去重
 * 
 *    跨域？
 *    答：使用jsonp解决跨域（dataType : 'jsonp'）、CORS解决跨域（Access-Control-Allow-Origin）、基于Nignx的服务
 * 
 *    排序算法？
 *    答：// 冒泡排序 每次将最小元素推至最前
        function sort4(array) {
            var len = array.length, i, j, tmp, result;
            result = array.slice(0);
            for (i = 0; i < len; i++) {
                for (j = len - 1; j > i; j--) {
                    if (result[j] < result[j - 1]) {
                        tmp = result[j - 1];
                        result[j - 1] = result[j];
                        result[j] = tmp;
                    }
                }
            }
            return result;
        }
        // 快速排序
        在数据集之中，选择一个元素作为"基准"（pivot）。
        所有小于"基准"的元素，都移到"基准"的左边；所有大于"基准"的元素，都移到"基准"的右边。
        对"基准"左边和右边的两个子集，不断重复第一步和第二步，直到所有子集只剩下一个元素为止。
        function sort6(array) {
            var tmp_array = array.slice(0), result,
            quickSort = function(arr) {
　　            if (arr.length <= 1) { return arr; }
　　            var pivotIndex = Math.floor(arr.length / 2);
　　            var pivot = arr.splice(pivotIndex, 1)[0];
　　            var left = [], right = [];
　　            for (var i = 0; i < arr.length; i++){
　　　　            if (arr[i] < pivot) {
　　　　　　            left.push(arr[i]);
　　　　            } else {
　　　　　　            right.push(arr[i]);
　　　　            }
　　            }
　　            return quickSort(left).concat([pivot], quickSort(right));
            };
            result = quickSort(tmp_array);
            return result;
        }
        // 选择排序 
        在无序区中选出最小的元素，然后将它和无序区的第一个元素交换位置。
        原理跟冒泡排序一样，算是冒泡的衍生版本
        function sort7(array) {
            var len = array.length, i, j, k, tmp, result;
            result = array.slice(0);
            for (i = 0; i < len; i++) {
                k = i;
            f   or (j = i + 1; j < len; j++) {
                    if (result[j] < result[k]) k = j;
                }
                if (k != i) {
                    tmp = result[k];
                    result[k] = result[i];
                    result[i] = tmp;
                }
            }
            return result;
        }
 * 
 *    箭头函数？
 *    答：1.箭头函数是匿名函数，不能作为构造函数，不能使用new
 *       2.箭头函数不绑定arguments，取而代之用rest参数...解决
 *       3.箭头函数不绑定this，会捕获其所在的上下文的this值，作为自己的this值
 *       4.箭头函数通过call()或apply()方法调用一个函数时，只传入了一个参数，对this并没有影响。
 *       5.箭头函数没有原型属性
 *       6.箭头函数不能当做Generator函数,不能使用yield关键字
 *       区别：箭头函数的this永远指向其上下文的this，任何方法都改变不了其指向，如call(),bind(),apply()；普通函数的this指向调用它的那个对象
 * 
 *    绑定this有几种方式？
 *    答：new绑定 > 显式绑定（call()、apply()、bind()） > 隐式绑定（方法调用） > 默认绑定
 * 
 *    用setTimeOut模拟setInterval？
 *    答：var i = 0;
         function time(){  //每隔1秒让++i
            console.log(++i);
            setTimeout(time,1000);
        }
        time();

 *    session与cookie的区别？
      答：1、cookie数据存放在客户端，session数据放在服务器上。
         2、cookie不是很安全，别人可以分析存放在本地的cookie并进行cookie欺骗，考虑到安全应当使用session。
         3、session会在一定时间内保存在服务器上，当访问增多，会比较占用你服务器的性能，考虑性能应当使用cookie。
         4、不同浏览器对cookie的数据大小限制不同，个数限制也不相同。
         5、可以考虑将登陆信息等重要信息存放为session，不重要的信息可以放在cookie中。
 */

/**
 * 二、vuex如何请求数据？vue的生命周期，单向数据流有什么好处，diff算法
 * 答：vuex如何请求数据？
 *     actions: {
		//async异步
		async getTodos({commit}) {
			const result = await axios.get('http://jsonplaceholder.typicode.com/todos?_limit=10');
			commit('updateState', result.data);
		},
		//Promise异步
		fetchTodos({commit}, params) {
			return new Promise((resolve, reject) => {
				fetch('http://jsonplaceholder.typicode.com/todos?_limit=5')
					.then(res => res.json())
					.then(data => {
						commit('setState', data)
						reject(data)
					}).catch(err => reject(err));	//抛出错误回调
			});
		}
    }

    vue的生命周期？
    beforeCreate（实例组件刚创建）
    created（数据data已经初始化完成，方法也已经可以调用，但是DOM为渲染，未挂载）
    beforeMount（DOM未完成挂载，数据也初始化完成，虚拟dom）
    mounted（数据和DOM都完成挂载）
    beforeUpdate（只要是页面数据改变了都会触发，数据更新之前，页面数据还是原来的数据）
    updated（只要是页面数据改变了都会触发，数据更新完毕，页面的数据是更新完成的）
    beforeDestroy
    destroyed

    单向数据流有什么好处？
    单向数据流：数据流动方向可以跟踪，流动单一，追查问题的时候可以跟快捷。缺点就是写起来不太方便。要使UI发生变更就必须创建各种action来维护对应的state
    双向流动：值和UI双绑定，这种好处大家都懂。但是由于各种数据相互依赖相互绑定，导致数据问题的源头难以被跟踪到，子组件修改父组件，兄弟组件互相修改有违设计原则。

    diff算法？
    比较只会在同层级进行, 不会跨层级比较。
 */

/**
 * 三、css布局，px em rem 的区别，css相关动画
 * 答：float布局、flex布局、grid布局。
 *     px表示“绝对尺寸”、em表示相对尺寸，其相对于当前对象内文本的font-size、rem也表示相对尺寸，其参考对象为根元素<html>的font-size
 *     transition(过渡)：transition: property duration timing-function delay;
 *     transform：transform: none|transform-functions;
 *     animation：animation: name duration timing-function delay iteration-count direction;
 */

/**
 * 四、h5移动端适配
 * 答：1.通过对界面进行等比例缩放；
 *    2.使用rem单位进行界面的适配
 */

/**
 * 五、web前端性能优化？
 * 答：减少HTTP请求，减少dns查找，内容分发网络，设置expires/cache-control头，设置内存时间，文件合并、压缩，异步加载
 */

/**
 * 六、H5，C3新特性有哪些？
 * 答：H5：1. 用于绘画 canvas 元素。 
 *        2. 用于媒介回放的 video 和 audio 元素。 
 *        3. 本地离线存储 localStorage 长期存储数据，浏览器关闭后数据不丢失；sessionStorage 的数据在浏览器关闭后自动删除。 
 *        4. 语意化更好的内容元素，比如 article、footer、header、nav、section 
 *        5. 表单控件，calendar、date、time、email、url、search。 
 *    C3：1.文本阴影text-shadow 
 *        2.边框圆角 border-radius 
 *        3.盒子阴影 box-shadow 
 *        4.边框图片boeder-image 
 *        5.背景大小 background-size 
 *        6.设置背景原点background-origin 
 *        7.background-clip背景区域裁切
 */

/**
 * 七、1.rem布局，em相关，为什么默认一个em是16px，以及CSS中还有哪些长度单位？
 *    答：1em = 16px;浏览器默认字体大小为16px。
 *       绝对长度：px,cm,in,mm,pt,px,px
 *       相对长度：%,em,rem,vh,vw,vmin,vmax,fr
 * 
 *    2.js中什么是变量提升？如果让你给全页面中的所有a标签的href属性的值后面加一个随机数，你会怎么做？
 *    答：在生成执行环境时，会有两个阶段。第一个阶段是创建的阶段，JS解释器会找出需要提升的变量和函数，并且给他们提前在内存中开辟好空间，函数的话会将整个函数存入内存中，变量只声明并且赋值为undefined，所以在第二个阶段，也就是代码执行阶段，我们可以直接提前使用。在提升的过程中，相同的函数会覆盖上一个函数，并且函数优先于变量提升
 *       $(document).click(function(){
            $("a").each(function(){
                if($(this).parent().parent().hasClass('list-unstyled')){
                    var href=$(this).attr("href");
                    var newHref=""
                    if(href.indexOf("&randomzzz=")>-1){
                        newHref=href.substring(0,href.indexOf("&randomzzz="));
                        $(this).attr("href",newHref+"&randomzzz="+Math.round(Math.random()*100000000000000));
                    }else{
                        $(this).attr("href",$(this).attr("href")+"&randomzzz="+Math.round(Math.random()*100000000000000));
                    }
                }
            })
        })

 *    3.循环for in 的缺点？
      答：for-in用来循环对象中的属性，但是通过for-in循环输出的属性名的顺序是不可测的。具体来说，所有属性都会被返回一次，但返回的先后次序可能会因浏览器而异。
         for-in会遍历原型链上的属性

 *    4.function a(){} 和var a=function(){} 有什么区别？
      答：var a = function(){}这个方法，必须先声明后使用！ function a(){}放在哪里都行，想在哪里声明就在哪里声明！

 *    5.如何实现页面内容懒加载？
      答：var num = document.getElementsByTagName('img').length;
        var img = document.getElementsByTagName("img");
        // 存储图片加载到的位置，避免每次都从第一张图片开始遍历
        var n = 0;
        // 页面载入完毕加载可视区域内的图片
        lazyLoad();                                
        window.onscroll = lazyLoad;
        // 监听页面滚动事件
        function lazyLoad() {
            // 可见区域高度
            var seeHeight = document.documentElement.clientHeight;
            // 滚动条距离顶部高度
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            for (var i = n; i < num; i++) {
                if (img[i].offsetTop < seeHeight + scrollTop) {
                    if (img[i].getAttribute("src") == "default.jpg") {
                        img[i].src = img[i].getAttribute("data-src");
                    }
                    n = i + 1;
                }
            }
        }

 *    6.文件上传有哪些实现方式？
      答：经典的form和input上传
         使用formData上传（var formData = new FormData();formData.append("file", file);）
         使用fileReader读取文件数据进行上传（var fr = new FileReader();fr.readAsDataURL(file);）

 *    7.pc&mible有什么区别？
      答：1.PC考虑的是浏览器的兼容性，而移动端开发考虑的更多的是手机兼容性，因为目前不管是android手机还是ios手机，一般浏览器使用的都是webkit内核，所以说做移动端开发，更多考虑的应该是手机分辨率的适配，和不同操作系统的略微差异化。
      2.在部分事件的处理上，移动端多出来的事件是触屏事件，而缺少的是hover事件。 另外包括移动端弹出的手机键盘的处理，这样的问题在PC端都是遇不到的。
      3.在布局上，移动端开发一般是要做到布局自适应的，需要熟练使用rem布局
      4.在动画处理上，PC端由于要考虑IE的兼容性，所以通常使用JS做动画的通用性会更好一些，但是CSS3做了很大的牺牲，而在手机端，如果要做一些动画、特效等，第一选择肯定是CSS3， 既简单、效率又高。
      5.微信的一些接口组好能去实现一遍，熟悉一下肯定是有好处的，比如通过微信分享文章，title、description、icon等图标的配置，这些还是要会的。
      6.百度地图的一些API接口对于移动端来说，LBS是一个非常重要的特性，所以地图这块肯定是要了解的，在加上百度地图这块已经是一个比较成熟的平台了，所以学起来也比较容易。7.CSS3的动画在移动端用的还是比较多的，但同时也要注意性能。
      8.一般PC端用jquery，移动端用zepto，因为移动端的流量还是比较重要的，所以引入的资源或者插件，能小则小，一个30k的资源和一个80k的资源，在移动端的差别还是挺大的。未压缩的jquery是262kb，压缩的jquey是83kb。未压缩的zepto是54kb，压缩的zepto只有9kb。
      9.最好能掌握一套完整的前端开发架构，比如模块化、打包、压缩、缓存有条件的还可以做一下自动化测试等等。
      10.性能优化，包括首屏的打开速度、用户响应延迟、渲染性能、动画帧率等在手机上都需要特别注意。
  
 *    8.首屏加载比较慢，你有哪些方法可以优化？
      答：通过webpack的UglifyJsPlugin插件对代码进行压缩
         提取第三方库
         通过webpack实现按需加载
         通过服务器对代码进行gzip压缩
         服务器端渲染首屏

 *    9.从输入URL到页面呈现的过程
      答：1、在浏览器地址栏输入url后，通过dns查询将域名转换为对应的IP地址（浏览器本地缓存，电脑缓存，路由器等中间缓存，域名服务器）；
         2、找到服务器的IP地址后，通过三次握手建立tcp连接，浏览器在建立好的tcp连接上发送http请求到服务端；
         3、服务端处理请求，并发送响应到浏览器端
         4、浏览器接收到响应数据（html文件），并解析html文件
         5、解析html文件时，首先将接收到的数据按照编码方式转化为单个字符，再通过浏览器规范将单个字符组合成对应的标记，然后根据规范将标记转化为包含对应属性的对象————dom节点，然后形成dom树
         6、在解析html文件时，会遇到<link>和<script>标签外链样式文件和脚本文件，其中css文件的加载不会阻塞dom树的构建，但会阻塞render树的构建；脚本文件在加载后会立即执行，并且加载和执行的过程都会阻塞dom树的构建。这里还有一点就是css文件的加载会阻塞脚本文件的执行，因为脚本文件可能会依赖css文件。
         7、加载好的css文件会按照类似的解析规则生成对应的css规则树，与dom树一起合并成render树，也就是浏览器中呈现页面所对应的内容结构。
         8、渲染render树时，首先计算好页面元素的占据空间信息和位置信息（回流），然后计算其背景色，字体颜色，边框颜色等外观信息（重绘），将所有元素都进行合成到一个复合图层上去，交给GPU进行渲染，最终呈现到浏览器中
 */

/**
 * 八、开发瓶颈？工作难题？
 * 1.树形数据结合模糊查询、精准定位
 * 2.微信公众号中文件缓存问题
 * 3.vuex数据存储刷新数据丢失问题
 * 4.webapp登陆功能
 * 
 */